﻿using System;
using System.Linq.Expressions;
using System.Windows.Input;
using System.ComponentModel;
using System.Windows;

namespace System.Windows.Input
{
    public abstract class CommandBase<T> : NotificationObject, IDelegateCommand
    {        
        private EventHandler _canExecuteHandler;
        private bool _isActive = true;

        public CommandBase() { }

        public CommandBase(bool isActive) : this()
        {
            _isActive = isActive;
        }

#region Additional Methods

        public virtual bool CanExecute(T parameter)
        {
            return IsActive && OnCanExecute(parameter); 
        }

        public virtual void Execute(T parameter)
        {
            if (CanExecute(parameter))
            {
                OnExecute(parameter);
                OnCommandExecuted(parameter);
            }
        }

        protected virtual void OnRequeryCanExecute()
        {
            if (_canExecuteHandler != null) _canExecuteHandler(this, EventArgs.Empty);
        }

#endregion

#region Abstract Methods

        protected abstract bool OnCanExecute(T parameter);

        protected abstract void OnExecute(T parameter);

#endregion

#region IDelegateCommand Members

        public bool IsActive
        {
            get
            {
                return _isActive;
            }
            set
            {
                SetProperty<bool>(ref _isActive, value);
                RequeryCanExecute();
            }
        }

        public void RequeryCanExecute()
        {
            OnRequeryCanExecute();
        }

#endregion

#region IReverseCommand Members

        public event EventHandler<CommandEventArgs> CommandExecuted;

#endregion

#region ICommand Members

        bool ICommand.CanExecute(object parameter)
        {
            return CanExecute((T)parameter);
        }

        event EventHandler ICommand.CanExecuteChanged
        {
            add { _canExecuteHandler += value; }
            remove { _canExecuteHandler -= value; }
        }

        void ICommand.Execute(object parameter)
        {
            Execute((T)parameter);
        }

#endregion

        protected void OnCommandExecuted(object parameter)
        {
            if (CommandExecuted != null)
                CommandExecuted(this, new CommandEventArgs(parameter));
        }

//#region IWeakEventListener Members

//        bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
//        {
//            RequeryCanExecute();
//            return true;        // as in always listening
//        }

//#endregion

    }
}